
package com.hlkj.pay.app.merchant.ext.impl.wxpay;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.security.PrivateKey;
import java.time.format.DateTimeFormatter;
import java.util.*;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.pojo.PageResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.extension.annotation.Extension;
import com.hlkj.pay.app.merchant.ext.ChannelMerchantComplaintExtPt;
import com.hlkj.pay.app.merchant.ext.MerchantExtConstant;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelComplaintOrderContext;
import com.hlkj.pay.app.merchant.ext.impl.wxpay.constant.ComplaintStatusType;
import com.hlkj.pay.app.merchant.ext.impl.wxpay.constant.WxPayExtConstant;
import com.hlkj.pay.app.merchant.ext.impl.wxpay.dto.*;
import com.hlkj.pay.app.merchant.ext.impl.wxpay.handler.WxPayCommonParamsHandle;
import com.hlkj.pay.common.MerchantResultCode;
import com.hlkj.pay.dto.order.notify.OrderComplaintNotifyDto;
import com.hlkj.pay.infrastructure.model.order.OrderComplaintChannelDO;
import com.hlkj.pay.infrastructure.model.order.OrderComplaintDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.service.order.IPayOrderService;
import com.hlkj.pay.util.DateUtils;
import com.hlkj.pay.util.HttpRequestUtil;
import com.hlkj.pay.util.MerchantUtils;
import com.ijpay.core.IJPayHttpResponse;
import com.ijpay.core.enums.AuthTypeEnum;
import com.ijpay.core.enums.RequestMethodEnum;
import com.ijpay.core.kit.PayKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.enums.WxDomainEnum;
import com.ijpay.wxpay.enums.v3.ComplaintsApiEnum;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 微信订单投诉操作
 * 
 * @author HlpayTeam
 * @date 2024/10/10 13:51
 */
@Slf4j
@Repository
@RequiredArgsConstructor
@Extension(bizId = MerchantExtConstant.CHANNEL_WX_PAY)
public class WxMerchantComplaintExtPt implements ChannelMerchantComplaintExtPt {

    private final WxPayCommonParamsHandle wxPayCommonParamsHandle;
    private final IPayOrderService payOrderService;
    @Override
    public CommonResult<List<OrderComplaintDO>> queryComplaintPage(ChannelComplaintOrderContext channelComplaintOrderContext) {

        log.info(" WxMerchantComplaintExtPt  queryComplaintPage 请求参数:{}", JsonUtils.toJsonString(channelComplaintOrderContext));
        OrderComplaintChannelDO orderComplaintChannelDO = channelComplaintOrderContext.getOrderComplaintChannelDO();
        CommonResult<WxPayConfig> wxPayConfigCommonResult = wxPayCommonParamsHandle.wxComplaintConfig(orderComplaintChannelDO,
                channelComplaintOrderContext.isTest());
        if (!wxPayConfigCommonResult.isSuccess()) {
            channelComplaintOrderContext.setRemark(wxPayConfigCommonResult.getMsg());
            channelComplaintOrderContext.setProcessStatus(false);
        }
        WxPayConfig wxPayConfig = wxPayConfigCommonResult.getData();

        try {
            // offset=0 才会有total 最大50条
            Map<String,Object> urlParams = new HashMap<>();
            urlParams.put("limit",50);
            urlParams.put("offset",0);
            // 进件之后的子商户号
            urlParams.put("complainted_mchid",orderComplaintChannelDO.getMchid());
            urlParams.put("begin_date", DateUtil.format(DateUtil.offsetDay(new Date(),-15), DatePattern.NORM_DATE_PATTERN));
            urlParams.put("end_date",DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN));

            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.GET,
                    WxDomainEnum.CHINA.toString(),
                    ComplaintsApiEnum.COMPLAINTS_V2.getUrl()+"?"+ HttpUtil.toParams(urlParams),
                    wxPayConfig.getMchId(),
                    wxPayConfig.getSerialNo(),
                    null,
                    wxPayConfig.getPrivateKeyPath(),
                    "",
                    AuthTypeEnum.RSA.getCode()
            );

            log.info("查询投诉列表返回参数:{}", response);
            if (response.getStatus() == WxPayExtConstant.OK ) {
                WxComplaintPageResp historyPageResp = JSONUtil.toBean(response.getBody(), WxComplaintPageResp.class);
                if(historyPageResp != null){
                    // 获取当前所有集合
                    List<WxComplaintDetailResp> pageResps = JSONUtil.toList(historyPageResp.getData(),WxComplaintDetailResp.class) ;
                    List<OrderComplaintDO> orderComplaintDOS = new ArrayList<>();
                    for(WxComplaintDetailResp detailResp:pageResps){
                        OrderComplaintDO orderComplaint = formatDetailResp(detailResp,wxPayConfig);
                        orderComplaintDOS.add(orderComplaint);
                    }
                    return CommonResult.success(orderComplaintDOS);
                }
            }else{
                channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
                if (StringUtils.hasText(response.getBody())) {
                    channelComplaintOrderContext.setRemark(response.getBody());
                }
                else {
                    channelComplaintOrderContext.setRemark("查询投诉列表返回错误信息为空,错误码为:" + response.getStatus());
                }
            }

        }catch (Exception e) {

            e.printStackTrace();
            log.error("查询投诉列表请求失败 message:{}", e.getMessage(), e);
            channelComplaintOrderContext.setRemark("查询投诉列表请求失败,失败信息" + e.getMessage());
            channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
        }

        return CommonResult.success();



    }

    @Override
    public CommonResult<OrderComplaintNotifyDto> queryComplaintDetail(ChannelComplaintOrderContext channelComplaintOrderContext) {

        log.info("queryComplaintDetail 请求参数:{}", JsonUtils.toJsonString(channelComplaintOrderContext));
        OrderComplaintChannelDO orderComplaintChannelDO = channelComplaintOrderContext.getOrderComplaintChannelDO();
        OrderComplaintDO orderComplaintDO = channelComplaintOrderContext.getOrderComplaintDO();
        CommonResult<WxPayConfig> wxPayConfigCommonResult = wxPayCommonParamsHandle.wxComplaintConfig(orderComplaintChannelDO,
                channelComplaintOrderContext.isTest());
        if (!wxPayConfigCommonResult.isSuccess()) {
            channelComplaintOrderContext.setRemark(wxPayConfigCommonResult.getMsg());
            channelComplaintOrderContext.setProcessStatus(false);
        }
        WxPayConfig wxPayConfig = wxPayConfigCommonResult.getData();

        try {

            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.GET,
                    WxDomainEnum.CHINA.toString(),
                    String.format(ComplaintsApiEnum.COMPLAINTS_DETAIL.toString(), orderComplaintDO.getComplaintId()),
                    wxPayConfig.getMchId(),
                    wxPayConfig.getSerialNo(),
                    null,
                    wxPayConfig.getPrivateKeyPath(),
                    "",
                    AuthTypeEnum.RSA.getCode()
            );

            if (response.getStatus() == WxPayExtConstant.OK ) {
                WxComplaintDetailResp wxComplaintDetailResp = JSONUtil.toBean(response.getBody(), WxComplaintDetailResp.class);
                channelComplaintOrderContext.setWxComplaintDetailResp(wxComplaintDetailResp);

                OrderComplaintDO orderComplaint = formatDetailResp(wxComplaintDetailResp,wxPayConfig);
                BeanUtil.copyProperties(orderComplaint,orderComplaintDO, CopyOptions.create().ignoreNullValue());
                channelComplaintOrderContext.setOrderComplaintDO(orderComplaintDO);
                log.info("queryComplaintDetail 返回参数:{}", JsonUtils.toJsonString(orderComplaintDO));

            }else{
                channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
                if (StringUtils.hasText(response.getBody())) {
                    channelComplaintOrderContext.setRemark(response.getBody());
                }
                else {
                    channelComplaintOrderContext.setRemark("微信查询投诉详情返回错误信息为空,错误码为:" + response.getStatus());
                }
            }

        }catch (Exception e) {
            e.printStackTrace();
            log.error("微信查询投诉详情请求失败 message:{}", e.getMessage(), e);
            channelComplaintOrderContext.setRemark("微信查询投诉详情请求失败,失败信息" + e.getMessage());
            channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
        }

        return CommonResult.success();
    }

    @Override
    public CommonResult<PageResult<WxComplaintHistoryDto>> queryComplaintHistory(ChannelComplaintOrderContext channelComplaintOrderContext) {

        log.info(" WxMerchantComplaintExtPt queryComplaintHistory 请求参数:{}", JsonUtils.toJsonString(channelComplaintOrderContext));
        OrderComplaintChannelDO orderComplaintChannelDO = channelComplaintOrderContext.getOrderComplaintChannelDO();
        OrderComplaintDO orderComplaintDO = channelComplaintOrderContext.getOrderComplaintDO();
        CommonResult<WxPayConfig> wxPayConfigCommonResult = wxPayCommonParamsHandle.wxComplaintConfig(orderComplaintChannelDO,
                channelComplaintOrderContext.isTest());
        if (!wxPayConfigCommonResult.isSuccess()) {
            channelComplaintOrderContext.setRemark(wxPayConfigCommonResult.getMsg());
            channelComplaintOrderContext.setProcessStatus(false);
        }
        WxPayConfig wxPayConfig = wxPayConfigCommonResult.getData();

        try {
            // offset=0 才会有total 默认返回最大300条 需手动分页
            Map<String,Integer> params = new HashMap<>();
            params.put("limit",300);
            params.put("offset",0);

            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.GET,
                    WxDomainEnum.CHINA.toString(),
                    String.format(ComplaintsApiEnum.COMPLAINTS_NEGOTIATION_HISTORY.getUrl()+"?"+ HttpUtil.toParams(params),orderComplaintDO.getComplaintId()),
                    wxPayConfig.getMchId(),
                    wxPayConfig.getSerialNo(),
                    null,
                    wxPayConfig.getPrivateKeyPath(),
                    "",
                    AuthTypeEnum.RSA.getCode()
            );

            log.info("查询投诉历史返回参数:{}", response);
            if (response.getStatus() == WxPayExtConstant.OK ) {
                WxComplaintPageResp historyPageResp = JSONUtil.toBean(response.getBody(), WxComplaintPageResp.class);
                if(historyPageResp != null){
                    PageResult<WxComplaintHistoryDto> pageResult = new PageResult();
                    pageResult.setTotal(historyPageResp.getTotal_count().longValue());
                    pageResult.setPageNo(channelComplaintOrderContext.getOffset().longValue());
                    pageResult.setPageSize(channelComplaintOrderContext.getLimit().longValue());
                    pageResult.setPages(Long.valueOf(NumberUtil.ceilDiv(historyPageResp.getTotal_count(),channelComplaintOrderContext.getLimit())));

                    // 获取当前所有集合
                    List<WxComplaintHistoryResp> historyResps = JSONUtil.toList(historyPageResp.getData(),WxComplaintHistoryResp.class) ;
                    // 按时间倒序
                    Collections.reverse(historyResps);
                    // 按页码截取数据
                    historyResps = CollUtil.sub(historyResps, PageUtil.getStart(channelComplaintOrderContext.getOffset()-1,channelComplaintOrderContext.getLimit()),PageUtil.getEnd(channelComplaintOrderContext.getOffset()-1,channelComplaintOrderContext.getLimit()));
                    List<WxComplaintHistoryDto> historyDtos = new ArrayList<>();
                    WxComplaintHistoryDto wxComplaintHistoryDto = null;
                    for(WxComplaintHistoryResp historyResp:historyResps){
                        wxComplaintHistoryDto = new WxComplaintHistoryDto();
                        wxComplaintHistoryDto.setOperator(historyResp.getOperator());
                        wxComplaintHistoryDto.setOperateType(wxPayCommonParamsHandle.complaintOperateType(historyResp.getOperate_type()));
                        wxComplaintHistoryDto.setOperateTime(DateUtils.shanghaiDate(historyResp.getOperate_time(),DateTimeFormatter.ISO_OFFSET_DATE_TIME));
                        wxComplaintHistoryDto.setOperateDetails(historyResp.getOperate_details());
                        wxComplaintHistoryDto.setMedias(getComplaintMedia(historyResp.getLog_id(),historyResp.getComplaint_media_list(),wxPayConfig));
                        historyDtos.add(wxComplaintHistoryDto);
                    }
                    pageResult.setList(historyDtos);
                    return CommonResult.success(pageResult);
                }
            }else{
                channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
                if (StringUtils.hasText(response.getBody())) {
                    channelComplaintOrderContext.setRemark(response.getBody());
                }
                else {
                    channelComplaintOrderContext.setRemark("查询投诉历史返回错误信息为空,错误码为:" + response.getStatus());
                }
            }

        }catch (Exception e) {

            e.printStackTrace();
            log.error("查询投诉历史请求失败 message:{}", e.getMessage(), e);
            channelComplaintOrderContext.setRemark("查询投诉历史请求失败,失败信息" + e.getMessage());
            channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
        }

        return CommonResult.success();

    }

    @Override
    public CommonResult<OrderComplaintNotifyDto> complaintStatusParse(HttpServletRequest request, ChannelComplaintOrderContext channelComplaintOrderContext) {
        CommonResult<OrderComplaintNotifyDto> orderComplaintNotifyDtoCommonResult = CommonResult.success();
        try {

            CommonResult<WxPayConfig> wxPayConfigCommonResult = wxPayCommonParamsHandle.wxComplaintConfig(channelComplaintOrderContext.getOrderComplaintChannelDO(),
                    channelComplaintOrderContext.isTest());
            if (!wxPayConfigCommonResult.isSuccess()) {
                channelComplaintOrderContext.setRemark(wxPayConfigCommonResult.getMsg());
                channelComplaintOrderContext.setProcessStatus(false);
            }
            WxPayConfig wxPayConfig = wxPayConfigCommonResult.getData();

            String timestamp = request.getHeader("Wechatpay-Timestamp");
            String nonce = request.getHeader("Wechatpay-Nonce");
            String serialNo = request.getHeader("Wechatpay-Serial");
            String signature = request.getHeader("Wechatpay-Signature");
            log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature);
            String result = HttpRequestUtil.requestBodyParams(request);
            log.info("微信投诉通知密文 {}", result);
            // String plainText = "{\"out_trade_no\":\"9965651481974950387712\",\"complaint_time\":\"2025-03-03T11:00:00+08:00\",\"amount\":12300,\"payer_phone\":\"13567230776\",\"complaint_detail\":\"我充值后还是用不了VPN\",\"complaint_state\":\"PAYER_COMPLAINTED\",\"transaction_id\":\"4200002519202503036857074987\",\"sub_mchid\":\"746798399\",\"complaint_handle_state\":\"MERCHANT_FULL_REFUNDED\",\"action_type\":\"MERCHANT_RESPONSE\",\"complaint_id\":\"200000020250303110255410899\"}";
            String plainText = null;
            // 微信公钥验证签名并解密
            if(serialNo.equals(wxPayConfig.getPayPublicId())){
                plainText = WxPayKit.verifyPublicKeyNotify(result, signature, nonce, timestamp,wxPayConfig.getApiV3Key(), wxPayConfig.getPayPublicPath());
            }else if(serialNo.equals(wxPayCommonParamsHandle.getPlatSerialNumber(wxPayConfig))){
                plainText = WxPayKit.verifyNotify(serialNo,result, signature, nonce, timestamp,wxPayConfig.getApiV3Key(), wxPayConfig.getPlatformCertPath());
            }
            log.info("微信投诉通知明文 {}", plainText);

            if (StrUtil.isEmpty(plainText)) {
                channelComplaintOrderContext.setProcessStatus(false);
                log.info("微信投诉回调验签不通过,signature:{}", signature);
                orderComplaintNotifyDtoCommonResult.setCode(MerchantResultCode.MERCHANT_CHANNEL_CALLBACK_SIGN_ERROR.getCode());
            }
            OrderComplaintNotifyDto orderComplaintNotifyDto=new OrderComplaintNotifyDto();
            orderComplaintNotifyDto.setCallBackBody(plainText);
            OrderComplaintDO complaintDO = new OrderComplaintDO();
            WxComplaintNotifyResp respData = JsonUtils.parseObject(plainText, WxComplaintNotifyResp.class);
            complaintDO.setComplaintId(respData.getComplaint_id());
            orderComplaintNotifyDto.setOrderComplaint(complaintDO);
            orderComplaintNotifyDtoCommonResult.setData(orderComplaintNotifyDto);
        }
        catch (Exception e) {
            channelComplaintOrderContext.setProcessStatus(false);
            orderComplaintNotifyDtoCommonResult.setCode(MerchantResultCode.MERCHANT_CHANNEL_CALLBACK_SIGN_ERROR.getCode());
        }

        log.info("微信投诉通知回调,解析后的订单数据为 payOrderDO:{}", JsonUtils.toJsonStringNotNull(orderComplaintNotifyDtoCommonResult.getData()));
        return orderComplaintNotifyDtoCommonResult;


    }

    @Override
    public CommonResult<String> queryComplaintNotify(ChannelComplaintOrderContext channelComplaintOrderContext) {
        log.info(" WxMerchantComplaintExtPt queryComplaintNotify 请求参数:{}", JsonUtils.toJsonString(channelComplaintOrderContext));
        OrderComplaintChannelDO orderComplaintChannelDO = channelComplaintOrderContext.getOrderComplaintChannelDO();
        CommonResult<WxPayConfig> wxPayConfigCommonResult = wxPayCommonParamsHandle.wxComplaintConfig(orderComplaintChannelDO,
                channelComplaintOrderContext.isTest());
        if (!wxPayConfigCommonResult.isSuccess()) {
            channelComplaintOrderContext.setRemark(wxPayConfigCommonResult.getMsg());
            channelComplaintOrderContext.setProcessStatus(false);
        }
        WxPayConfig wxPayConfig = wxPayConfigCommonResult.getData();

        try {

            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.GET,
                    WxDomainEnum.CHINA.toString(),
                    ComplaintsApiEnum.COMPLAINTS_NOTIFICATION.toString(),
                    wxPayConfig.getMchId(),
                    wxPayConfig.getSerialNo(),
                    null,
                    wxPayConfig.getPrivateKeyPath(),
                    "",
                    AuthTypeEnum.RSA.getCode()
            );

            log.info("查询回调通知地址返回参数:{}", response);
            if (response.getStatus() == WxPayExtConstant.OK) {
                JSONObject resp = JSONUtil.parseObj(response.getBody());
                String url = resp.getStr("url");
                if(StrUtil.isNotEmpty(url)){
                    return CommonResult.success(url);
                }
            }else{
                channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
                if (StringUtils.hasText(response.getBody())) {
                    channelComplaintOrderContext.setRemark(response.getBody());
                }
                else {
                    channelComplaintOrderContext.setRemark("查询回调通知地址返回错误信息为空,错误码为:" + response.getStatus());
                }
            }

        }catch (Exception e) {
            e.printStackTrace();
            log.error("查询回调通知请求失败 message:{}", e.getMessage(), e);
            channelComplaintOrderContext.setRemark("查询回调通知地址请求失败,失败信息" + e.getMessage());
            channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
        }
        return CommonResult.success();
    }

    @Override
    public CommonResult<String> saveComplaintNotify(ChannelComplaintOrderContext channelComplaintOrderContext) {

        log.info(" WxMerchantComplaintExtPt 请求参数:{}", JsonUtils.toJsonString(channelComplaintOrderContext));
        OrderComplaintChannelDO orderComplaintChannelDO = channelComplaintOrderContext.getOrderComplaintChannelDO();
        CommonResult<WxPayConfig> wxPayConfigCommonResult = wxPayCommonParamsHandle.wxComplaintConfig(orderComplaintChannelDO,
                channelComplaintOrderContext.isTest());
        if (!wxPayConfigCommonResult.isSuccess()) {
            channelComplaintOrderContext.setRemark(wxPayConfigCommonResult.getMsg());
            channelComplaintOrderContext.setProcessStatus(false);
        }
        WxPayConfig wxPayConfig = wxPayConfigCommonResult.getData();

        try {
            // 判断是否更新
            RequestMethodEnum requestMethodEnum = RequestMethodEnum.POST;
            if(orderComplaintChannelDO.getNotifyFlag() != null && orderComplaintChannelDO.getNotifyFlag() == 1){
                requestMethodEnum = RequestMethodEnum.PUT;
            }

            Map<String,String> params = new HashMap<>();
            params.put("url",channelComplaintOrderContext.getComplaintNotifyUrl());

            IJPayHttpResponse response = WxPayApi.v3(
                    requestMethodEnum,
                    WxDomainEnum.CHINA.toString(),
                    ComplaintsApiEnum.COMPLAINTS_NOTIFICATION.toString(),
                    wxPayConfig.getMchId(),
                    wxPayConfig.getSerialNo(),
                    wxPayConfig.getPayPublicId(),
                    wxPayConfig.getPrivateKeyPath(),
                    JSONUtil.toJsonStr(params),
                    AuthTypeEnum.RSA.getCode()
            );

            log.info("更新回调通知地址返回参数:{}", response);
            // 微信支付公钥验证签名
            boolean verifySignature = WxPayKit.verifyPublicKeySignature(response, wxPayConfig.getPayPublicPath());
            if(verifySignature){
                if (response.getStatus() == WxPayExtConstant.OK) {
                    JSONObject resp = JSONUtil.parseObj(response.getBody());
                    String url = resp.getStr("url");
                    if(StrUtil.isNotEmpty(url)){
                        return CommonResult.success(url);
                    }
                }else{
                    channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
                    if (StringUtils.hasText(response.getBody())) {
                        channelComplaintOrderContext.setRemark(response.getBody());
                    }
                    else {
                        channelComplaintOrderContext.setRemark("更新回调通知地址返回错误信息为空,错误码为:" + response.getStatus());
                    }
                }
            }else{
                channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
                channelComplaintOrderContext.setRemark("更新回调通知地址支付公钥验签失败, " + wxPayConfig.getPayPublicPath());
            }


        }catch (Exception e) {
            e.printStackTrace();
            log.error("更新回调通知请求失败 message:{}", e.getMessage(), e);
            channelComplaintOrderContext.setRemark("更新回调通知地址请求失败,失败信息" + e.getMessage());
            channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
        }
        return CommonResult.success();
    }

    @Override
    public CommonResult<String> replyUser(ChannelComplaintOrderContext channelComplaintOrderContext) {

        log.info(" WxMerchantComplaintExtPt replyUser 请求参数:{}", JsonUtils.toJsonString(channelComplaintOrderContext));
        OrderComplaintChannelDO orderComplaintChannelDO = channelComplaintOrderContext.getOrderComplaintChannelDO();
        OrderComplaintDO orderComplaintDO = channelComplaintOrderContext.getOrderComplaintDO();
        CommonResult<WxPayConfig> wxPayConfigCommonResult = wxPayCommonParamsHandle.wxComplaintConfig(orderComplaintChannelDO,
                channelComplaintOrderContext.isTest());
        if (!wxPayConfigCommonResult.isSuccess()) {
            channelComplaintOrderContext.setRemark(wxPayConfigCommonResult.getMsg());
            channelComplaintOrderContext.setProcessStatus(false);
        }
        WxPayConfig wxPayConfig = wxPayConfigCommonResult.getData();

        try {
            Map<String,Object> params = new HashMap<>();
            params.put("complainted_mchid",orderComplaintDO.getAppId());
            params.put("response_content",channelComplaintOrderContext.getContent());
            if(CollUtil.isNotEmpty(channelComplaintOrderContext.getImgUrls())){
                params.put("response_images",getImgMedias(channelComplaintOrderContext.getImgUrls(),wxPayConfig));
            }

            log.info(JSONUtil.toJsonStr(params));

            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.POST,
                    WxDomainEnum.CHINA.toString(),
                    String.format(ComplaintsApiEnum.COMPLAINTS_RESPONSE.toString(), orderComplaintDO.getComplaintId()),
                    wxPayConfig.getMchId(),
                    wxPayConfig.getSerialNo(),
                    null,
                    wxPayConfig.getPrivateKeyPath(),
                    JSONUtil.toJsonStr(params),
                    AuthTypeEnum.RSA.getCode()
            );

            log.info("微信投诉回复用户返回参数:{}", response);
            if (response.getStatus() == 204 ) {
                log.info("微信投诉回复用户成功:{}", response);
            }else{
                channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
                if (StringUtils.hasText(response.getBody())) {
                    channelComplaintOrderContext.setRemark(response.getBody());
                }
                else {
                    channelComplaintOrderContext.setRemark("微信投诉回复用户返回错误信息为空,错误码为:" + response.getStatus());
                }
            }

        }catch (Exception e) {

            e.printStackTrace();
            log.error("微信投诉回复用户请求失败 message:{}", e.getMessage(), e);
            channelComplaintOrderContext.setRemark("微信投诉回复用户请求失败,失败信息" + e.getMessage());
            channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
        }

        return CommonResult.success();

    }

    @Override
    public CommonResult<String> completeComplaint(ChannelComplaintOrderContext channelComplaintOrderContext) {

        log.info(" WxMerchantComplaintExtPt completeComplaint 请求参数:{}", JsonUtils.toJsonString(channelComplaintOrderContext));
        OrderComplaintChannelDO orderComplaintChannelDO = channelComplaintOrderContext.getOrderComplaintChannelDO();
        OrderComplaintDO orderComplaintDO = channelComplaintOrderContext.getOrderComplaintDO();
        CommonResult<WxPayConfig> wxPayConfigCommonResult = wxPayCommonParamsHandle.wxComplaintConfig(orderComplaintChannelDO,
                channelComplaintOrderContext.isTest());
        if (!wxPayConfigCommonResult.isSuccess()) {
            channelComplaintOrderContext.setRemark(wxPayConfigCommonResult.getMsg());
            channelComplaintOrderContext.setProcessStatus(false);
        }
        WxPayConfig wxPayConfig = wxPayConfigCommonResult.getData();

        try {
            Map<String,Object> params = new HashMap<>();
            params.put("complainted_mchid",orderComplaintDO.getAppId());

            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.POST,
                    WxDomainEnum.CHINA.toString(),
                    String.format(ComplaintsApiEnum.COMPLAINTS_COMPLETE.toString(), orderComplaintDO.getComplaintId()),
                    wxPayConfig.getMchId(),
                    wxPayConfig.getSerialNo(),
                    null,
                    wxPayConfig.getPrivateKeyPath(),
                    JSONUtil.toJsonStr(params),
                    AuthTypeEnum.RSA.getCode()
            );

            log.info("微信投诉处理完成返回参数:{}", response);
            if (response.getStatus() == 204 ) {
                log.info("微信投诉处理成功:{}", response);
            }else{
                channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
                if (StringUtils.hasText(response.getBody())) {
                    channelComplaintOrderContext.setRemark(response.getBody());
                }
                else {
                    channelComplaintOrderContext.setRemark("微信投诉处理完成返回错误信息为空,错误码为:" + response.getStatus());
                }
            }

        }catch (Exception e) {
            e.printStackTrace();
            log.error("微信投诉处理完成请求失败 message:{}", e.getMessage(), e);
            channelComplaintOrderContext.setRemark("微信投诉处理完成请求失败,失败信息" + e.getMessage());
            channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
        }

        return CommonResult.success();

    }

    @Override
    public CommonResult<String> updateComplaintProgress(ChannelComplaintOrderContext channelComplaintOrderContext) {

        log.info(" WxMerchantComplaintExtPt updateComplaintProgress 请求参数:{}", JsonUtils.toJsonString(channelComplaintOrderContext));
        OrderComplaintChannelDO orderComplaintChannelDO = channelComplaintOrderContext.getOrderComplaintChannelDO();
        OrderComplaintDO orderComplaintDO = channelComplaintOrderContext.getOrderComplaintDO();
        CommonResult<WxPayConfig> wxPayConfigCommonResult = wxPayCommonParamsHandle.wxComplaintConfig(orderComplaintChannelDO,
                channelComplaintOrderContext.isTest());
        if (!wxPayConfigCommonResult.isSuccess()) {
            channelComplaintOrderContext.setRemark(wxPayConfigCommonResult.getMsg());
            channelComplaintOrderContext.setProcessStatus(false);
            return CommonResult.error(0,wxPayConfigCommonResult.getMsg());
        }
        WxPayConfig wxPayConfig = wxPayConfigCommonResult.getData();

        try {
            Map<String,Object> params = new HashMap<>();
            switch (channelComplaintOrderContext.getAction()){
                case 0:
                    params.put("action","REJECT");
                    params.put("reject_reason",channelComplaintOrderContext.getContent());
                    params.put("reject_media_list",getImgMedias(channelComplaintOrderContext.getImgUrls(),wxPayConfig));
                    params.put("remark",channelComplaintOrderContext.getRemark());
                    break;
                case 1:
                    params.put("action","APPROVE");
                    break;
            }

            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.POST,
                    WxDomainEnum.CHINA.toString(),
                    String.format("/v3/merchant-service/complaints-v2/%s/update-refund-progress", orderComplaintDO.getComplaintId()),
                    wxPayConfig.getMchId(),
                    wxPayConfig.getSerialNo(),
                    null,
                    wxPayConfig.getPrivateKeyPath(),
                    JSONUtil.toJsonStr(params),
                    AuthTypeEnum.RSA.getCode()
            );

            log.info("微信更新退款审批返回参数:{}", response);
            if (response.getStatus() == WxPayExtConstant.OK) {
                JSONObject resp = JSONUtil.parseObj(response.getBody());
            }else{
                channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
                if (StringUtils.hasText(response.getBody())) {
                    channelComplaintOrderContext.setRemark(response.getBody());
                }
                else {
                    channelComplaintOrderContext.setRemark("微信更新退款审批返回错误信息为空,错误码为:" + response.getStatus());
                }
            }

        }catch (Exception e) {
            e.printStackTrace();
            log.error("微信更新退款审批请求失败 message:{}", e.getMessage(), e);
            channelComplaintOrderContext.setRemark("微信更新退款审批请求失败,失败信息" + e.getMessage());
            channelComplaintOrderContext.setProcessStatus(Boolean.FALSE);
        }

        return CommonResult.success();

    }

    @Override
    public String callBackResponse(CommonResult commonResult) {
        if (commonResult.isSuccess()) {
            return "SUCCESS";
        }
        else {
            return "FAIL";
        }
    }


    private WxComplaintDetailResp.ComplaintOrderInfo getOutTradeOrderInfo(List<WxComplaintDetailResp.ComplaintOrderInfo> list){

        if(CollUtil.isEmpty(list)){
            return null;
        }
        return list.get(0);
    }

    /**
     * 微信media转可预览的url
     * @param id     logId
     * @param media  微信媒体资源信息
     * @param wxPayConfig
     * @return
     */
    private OrderComplaintMediaDto getComplaintMedia(String id,ComplaintMediaDto media,WxPayConfig wxPayConfig){

        if(media == null){
            return null;
        }
        OrderComplaintMediaDto complaintMediaDto = new OrderComplaintMediaDto();
        complaintMediaDto.setMediaType(media.getMedia_type());
        complaintMediaDto.setMediaId(wxPayCommonParamsHandle.getImgUrls(id,media.getMedia_url(),null));
        complaintMediaDto.setUrl(wxPayCommonParamsHandle.getImgUrls(id,media.getMedia_url(),wxPayConfig));
        complaintMediaDto.setId(id);
        return complaintMediaDto;
    }
    private List<OrderComplaintMediaDto> getComplaintMedias(String id,List<ComplaintMediaDto> medias,WxPayConfig wxPayConfig){

        List<OrderComplaintMediaDto> mediaList = new ArrayList<>();
        if(CollUtil.isEmpty(medias)){
            return mediaList;
        }
        for(ComplaintMediaDto media:medias){
            mediaList.add(getComplaintMedia(id,media,wxPayConfig));
        }
        return mediaList;
    }

    private List<String> getImgMedias(List<String> imgs,WxPayConfig wxPayConfig){
        List<String> medias = new ArrayList<>();
        String media = null;
        for(String img:imgs){
            media = wxPayCommonParamsHandle.getV3UploadFileMediaId(img,wxPayConfig,ComplaintsApiEnum.IMAGES_UPLOAD.toString());
            if(StrUtil.isNotEmpty(media)){
                medias.add(media);
            }
        }
        return medias;
    }

    /**
     * 微信投诉详情本地序列化
     * @param wxComplaintDetailResp  微信投诉详情
     * @param wxPayConfig            渠道配置
     * @return
     * @throws Exception
     */
    public OrderComplaintDO formatDetailResp(WxComplaintDetailResp wxComplaintDetailResp,WxPayConfig wxPayConfig) throws Exception {

        // 获取私钥
        PrivateKey privateKey = PayKit.getPrivateKey(wxPayConfig.getPrivateKeyPath(), AuthTypeEnum.RSA.getCode());

        OrderComplaintDO orderComplaintDO = new OrderComplaintDO();
        if(StrUtil.isNotEmpty(wxComplaintDetailResp.getPayer_phone())){
            orderComplaintDO.setPhone(PayKit.rsaDecryptOAEP(wxComplaintDetailResp.getPayer_phone(),privateKey));
        }
        orderComplaintDO.setDetail(wxComplaintDetailResp.getComplaint_detail());
        orderComplaintDO.setCreateTime(DateUtils.shanghaiDate(wxComplaintDetailResp.getComplaint_time(), DateTimeFormatter.ISO_OFFSET_DATE_TIME));
        orderComplaintDO.setAppId(wxComplaintDetailResp.getComplainted_mchid());
        orderComplaintDO.setComplaintId(wxComplaintDetailResp.getComplaint_id());

        WxComplaintDetailResp.ComplaintOrderInfo orderInfo = getOutTradeOrderInfo(wxComplaintDetailResp.getComplaint_order_info());
        if(orderInfo != null){
            orderComplaintDO.setWxOrderNo(orderInfo.getTransaction_id());
            orderComplaintDO.setMchOrderNo(orderInfo.getOut_trade_no());
            orderComplaintDO.setAmount(MerchantUtils.fenToYuan(orderInfo.getAmount()));
        }
        orderComplaintDO.setStatus(ComplaintStatusType.getCode(wxComplaintDetailResp.getComplaint_state()));
        orderComplaintDO.setProblemDesc(wxComplaintDetailResp.getProblem_description());
        orderComplaintDO.setProblemType( wxPayCommonParamsHandle.problemType(wxComplaintDetailResp.getProblem_type()));
        orderComplaintDO.setRefundAmount(MerchantUtils.fenToYuan(wxComplaintDetailResp.getApply_refund_amount()));
        orderComplaintDO.setNum(wxComplaintDetailResp.getUser_complaint_times());
        orderComplaintDO.setPlatform(wxPayCommonParamsHandle.foramtBoolean(wxComplaintDetailResp.getIn_platform_service()));
        orderComplaintDO.setResponse(wxPayCommonParamsHandle.foramtBoolean(wxComplaintDetailResp.getIncoming_user_response()));
        orderComplaintDO.setRefunded(wxPayCommonParamsHandle.foramtBoolean(wxComplaintDetailResp.getComplaint_full_refunded()));

        // 投诉图片
        List<OrderComplaintMediaDto> medias = getComplaintMedias(wxComplaintDetailResp.getComplaint_id(),wxComplaintDetailResp.getComplaint_media_list(),wxPayConfig) ;
        if(CollUtil.isNotEmpty(medias)){
            orderComplaintDO.setComplaintMedias(medias);
            orderComplaintDO.setComplaintMediaJson(JSONUtil.toJsonStr(medias));
        }
        // 获取订单SN
        PayOrderDO payOrderDO = payOrderService.queryWxAssociatedOrder(orderComplaintDO.getWxOrderNo());
        if(payOrderDO != null){
            orderComplaintDO.setSn(payOrderDO.getSn());
            orderComplaintDO.setPayOrderNo(payOrderDO.getPayOrderNo());
            orderComplaintDO.setChannelCode(payOrderDO.getChannelCode());
            orderComplaintDO.setProviderCode(payOrderDO.getProviderCode());
        }
        return orderComplaintDO;
    }



}
